﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.ObjectMapping;
using Abp.Runtime.Caching;
using AutoMapper.QueryableExtensions;
using FwProject.Authorization.Users;
using FwProject.Core.Distribution;
using FwProject.Core.Restaurant;
using FwProject.Manager;
using FwProject.Restaurant.Dto;
using FwProject.PublicService.SqlExec;
using X.PagedList;
using Abp.UI;
namespace FwProject.Restaurant
{
    [AbpAuthorize]
    public class RestaurantUserAppService : FwProjectAppServiceBase, IRestaurantUserAppService
    {
        public readonly IRepository<RestaurantUserInfo, Guid> _repositoryRestaurantUserInfo;
        public readonly IRepository<User, long> _repositoryUser;
        private readonly RestaurantUserManager _restaurantuserManager;
        private readonly ISqlExecuter _sqlExecuter;
        public readonly IRepository<DistributionInfoDetails, Guid> _repositoryDistributionInfo;
        private readonly RestaurantInfoManager _restaurantManager;
        public readonly IRepository<RestaurantInfo, Guid> _repositoryRestaurantInfo;
        public readonly ICacheManager _catchmanager;
        public IGuidGenerator _guid { get; set; }
        public IObjectMapper _map { get; set; }
        public RestaurantUserAppService(
            ICacheManager catchmanager, IRepository<User, long> repositoryUser,
            IRepository<RestaurantUserInfo, Guid> repositoryRestaurantUserInfo, RestaurantUserManager restaurantuserManager,
            UserManager _userManager, RestaurantInfoManager restaurantManager,
            IRepository<DistributionInfoDetails, Guid> repositoryDistributionInfo,
            IRepository<RestaurantInfo, Guid> repositoryRestaurantInfo, ISqlExecuter sqlExecuter
            )
        {
            _repositoryRestaurantInfo = repositoryRestaurantInfo;
            _sqlExecuter = sqlExecuter;
            _repositoryDistributionInfo = repositoryDistributionInfo;
            _restaurantManager = restaurantManager;
            _catchmanager = catchmanager;
            _repositoryUser = repositoryUser;
            _repositoryRestaurantUserInfo = repositoryRestaurantUserInfo;
            _restaurantuserManager = restaurantuserManager;
            _guid = SequentialGuidGenerator.Instance;
        }

        /// <summary>
        /// 创建一个餐厅人员
        /// </summary>
        /// <returns>The create.</returns>
        /// <param name="input">Input.</param>
        public async Task<Guid> Create(RestaurantUserInput input)
        {
            var model = _map.Map<RestaurantUserInfo>(input);
            model.Id = _guid.Create();
            return await _restaurantuserManager.CreateRestaurantUser(model);
        }

        /// <summary>
        /// 获取餐厅人员信息
        /// </summary>
        /// <returns>The by identifier async.</returns>
        /// <param name="id">Identifier.</param>
        public async Task<RestaurantUserDto> GetByIdAsync(Guid id)
        {
            var model = (await GetCache).Where(o => o.Id == id).FirstOrDefault();
            return _map.Map<RestaurantUserDto>(model);

        }
        /// <summary>
        /// 获取餐厅人员列表
        /// </summary>
        /// <returns>The restaurant paged list async.</returns>
        /// <param name="餐厅绑定人员编号">Page index.</param>
        public async Task<IPagedList<RestaurantUserDto>> GetPagedListAsync(int pageIdx, int pageSize, DateTime? begindateTime, DateTime? enddatetime)
        {
            var listmodel = (await GetCache).AsQueryable();
            if (begindateTime != null)
                listmodel.Where(o => o.CreationTime >= begindateTime);

            if (enddatetime != null)
                listmodel.Where(o => o.CreationTime <= enddatetime);

            var model = _repositoryRestaurantUserInfo.GetAll().Where(o => o.EmployeeRestaurantId == AbpSession.UserId.Value).FirstOrDefault();
            return await listmodel.Where(o => o.Id == model.Id).OrderByDescending(m => m.Id).ProjectTo<RestaurantUserDto>().ToPagedListAsync(pageIdx, pageSize);

        }
        /// <summary>
        /// 押金统计
        /// </summary>
        /// <returns></returns>
        public async Task<IPagedList<RestaurantUserDto>> GetDepositPagedListAsync(int pageIdx, int pageSize, DateTime? begindateTime, DateTime? enddatetime, string restaurantName, string isDeposit)
        {
            var listmodel = _repositoryRestaurantUserInfo.GetAllIncluding(O => O.EmployeeRestauranUser, O => O.RestaurantInfoModel).OrderByDescending(m => m.CreationTime).AsQueryable();
            if (!string.IsNullOrEmpty(restaurantName))
                listmodel = listmodel.Where(o => o.RestaurantInfoModel.RestaurantName.Contains(restaurantName));

            if (isDeposit == "1")
                listmodel = listmodel.Where(o => o.RestaurantInfoModel.Deposit > 0 || o.RestaurantInfoModel.Deposit<0);
            if (isDeposit == "0")
                listmodel = listmodel.Where(o => o.RestaurantInfoModel.Deposit == 0);

            if (begindateTime != null)
                listmodel = listmodel.Where(o => o.RestaurantInfoModel.DepositDate >= begindateTime);

            if (enddatetime != null)
                listmodel = listmodel.Where(o => o.RestaurantInfoModel.DepositDate <= enddatetime.Value.AddHours(24));

            return await listmodel.Where(o => o.RestaurantInfoModel.IsDeleted == false).ProjectTo<RestaurantUserDto>().ToPagedListAsync(pageIdx, pageSize);
        }
        /// <summary>
        /// 押金统计导出
        /// </summary>
        /// <returns></returns>
        public async Task<List<ExportDepositStatisticsDto>> GetExportDepositListAsync(DateTime? begindateTime, DateTime? enddatetime, string restaurantName, string isDeposit)
        {
            string sql = $@"select RestaurantName,DepositDate,Deposit,Name,b.Mobile,b.IsDeleted from RestaurantUserInfo a,RestaurantInfo b,AbpUsers c where a.RestaurantInfoId = b.Id and a.EmployeeRestaurantId = c.Id and b.IsDeleted=0 order by b.DepositDate desc";

            var listmodel = _sqlExecuter.FromDapperSqlQuery<ExportDepositStatisticsDto>(sql, null).AsQueryable();

            if (!string.IsNullOrEmpty(restaurantName))
                listmodel = listmodel.Where(o => o.RestaurantName.Contains(restaurantName));

            if (isDeposit == "1")
                listmodel = listmodel.Where(o => o.Deposit > 0 || o.Deposit < 0);
            if (isDeposit == "0")
                listmodel = listmodel.Where(o => o.Deposit == 0.00);

            if (begindateTime != null)
                listmodel = listmodel.Where(o => o.DepositDate >= begindateTime);

            if (enddatetime != null)
                listmodel = listmodel.Where(o => o.DepositDate <= enddatetime.Value.AddHours(24));

            return await listmodel.ToListAsync();
        }

        /// <summary>
        /// 修改餐厅人员信息
        /// </summary>
        /// <returns>The update.</returns>
        /// <param name="id">Identifier.</param>
        /// <param name="input">Input.</param>
        public async Task Update(Guid id, RestaurantUserInput input)
        {
            var model = await _repositoryRestaurantUserInfo.GetAsync(id);
            model = _map.Map(input, model);
            await _restaurantuserManager.UpdateRestaurantUser(model);

        }
        public async Task<RestaurantUserDto> GetOneUser(Guid RestaurantInfoId)
        {
            var listmodel = (await GetCache).AsQueryable();
            var model = listmodel.Where(o => o.RestaurantInfoId == RestaurantInfoId).FirstOrDefault();
            return _map.Map<RestaurantUserDto>(model);
        }


        /// <summary>
        /// 根据当前用户获取餐厅信息
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<Tuple<RestaurantUserDto, int, int>> GetByUserAppRestaurant(long userId)
        {
            var listmodel = (await GetCache).AsQueryable();
            var model = listmodel.Where(o => o.EmployeeRestaurantId == userId).FirstOrDefault();
            int? count = 0;
            int i = 0;
            if (model != null)
            {
                try
                {
                    count = GetTopCatch.Where(o => o.Id == model.RestaurantInfoId).FirstOrDefault()?.Distributioncount??0;
                    foreach (var item in GetTopCatch)
                    {
                        i++;
                        if (item.Id == model.RestaurantInfoId)
                        {
                            count = item.Distributioncount;
                            break;
                        }

                    }
                }
                catch (Exception exe)
                {

                    throw;
                }


            }
            else {
                throw new UserFriendlyException("账户未绑定餐厅");
            }

            return Tuple.Create<RestaurantUserDto, int, int>(_map.Map<RestaurantUserDto>(model), count.Value, i);
        }

        /// <summary>
        /// 根据当前用户获取餐厅信息
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<RestaurantUserDto> GetByUserRestaurant(long userId)
        {
            var listmodel = (await GetCache).AsQueryable();
            var model = listmodel.Where(o => o.EmployeeRestaurantId == userId).FirstOrDefault();


            return _map.Map<RestaurantUserDto>(model);
        }

        /// <summary>
        /// 获取餐厅的绑定人员
        /// </summary>
        /// <param name="retaurantid"></param>
        /// <returns></returns>
        public async Task<List<RestaurantUserDto>> GetAllByRetaurantAsync(Guid retaurantid)
        {
            var query = (await GetCache).AsQueryable().Where(o => o.RestaurantInfoId == retaurantid);
            var data = _map.Map<List<RestaurantUserDto>>(query);
            return data;
        }



        private Task<List<RestaurantUserInfo>> GetCache
        {
            get
            {
                ICache cache = _catchmanager.GetCache(nameof(RestaurantUserInfo));
                return cache.GetAsync("list", async () => await _repositoryRestaurantUserInfo.GetAllIncluding(O => O.EmployeeRestauranUser, O => O.RestaurantInfoModel).OrderByDescending(m => m.CreationTime).ToListAsync());
            }

        }

        private List<AppTopRestaurantDto> GetTopCatch
        {
            get
            {

                ICache cache = _catchmanager.GetCache(nameof(AppTopRestaurantDto));
                return cache.Get($"toplist", () => modelist());

            }

        }

        private List<AppTopRestaurantDto> modelist()
        {
            List<AppTopRestaurantDto> list = new List<AppTopRestaurantDto>();
            var RestaurantUsermodel = _repositoryRestaurantUserInfo.GetAll().Where(o => o.EmployeeRestaurantId == AbpSession.UserId.Value).FirstOrDefault();
            var Restaurant = _repositoryRestaurantInfo.Get(RestaurantUsermodel.RestaurantInfoId.Value);
            string sql = string.Format($@"select isnull(b.Distributioncount,0) Distributioncount ,a.RestaurantName,a.Thump,a.Id  from RestaurantInfo a 
                                    left join (select a.Restaurantid, SUM(b.Distributioncount*c.[Count]) Distributioncount from DistributionInfo a left join DistributionInfoDetails b 
                                    on b.DistributionInfoId=a.Id left join TypeNumberInfo c on c.Id=b.TypeNumberInfoId
                                     group by a.Restaurantid
                                     ) as b on a.Id=b.Restaurantid
                                    where [dbo].[fnGetDistanceNew] ('{Restaurant.longitude}','{Restaurant.latitude}',a.longitude,a.latitude)<=3
                                    order by Distributioncount desc");
            try
            {
                list= _sqlExecuter.FromSqlQuery<AppTopRestaurantDto>(sql, null).ToList();
            }
            catch (Exception)
            {

                throw;
            }
            return list;

        }


    }
}
